<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Embedding state-machine-cat scripts in html</title>
    <meta
      http-equiv="content-security-policy"
      content="
        connect-src 'self';
        font-src 'none';
        frame-src 'none';
        img-src 'self' data:;
        manifest-src 'self';
        media-src 'none';
        object-src 'none';
        script-src 'self' 'unsafe-eval';
        style-src 'unsafe-inline';
        form-action 'none';
        navigate-to 'none'"
    />
    <script
      src="state-machine-cat-inpage.min.js"
      type="module"
      defer
      integrity="sha512-Gkmckt5qb5VZgVPVEYJnrtE2gKujpyN6zkW3EG2okWZ1/R9hFRxfPNvB4ACb/70Z0dXsLH4xDi0Mrm8SDZMoJQ=="
    ></script>
    <style>
      body { font-family: sans-serif; margin: 0 auto; max-width: 799px;
      line-height: 1.6; font-size: 18px; padding-bottom: 3em; background-color:
      #fff; } th{ text-align: left; background-color: #eee}
      tr:nth-child(even) { background-color: #f3f3f3} pre {
      background-color:#eee; font-size:smaller} h1, h2, h3 { line-height: 1.2}
      table,tr,th,td {font-size: inherit} table {padding-top:1em}
    </style>
  </head>

  <body>
    <h1>Embedding state-machine-cat scripts in html</h1>
    <p>
      In your
      <code>head</code>:
    </p>

    <pre>&lt;script
      src="https://state-machine-cat.js.org/state-machine-cat-inpage.min.js"
      type="module" defer> &lt;/script></pre>

    <p>In your <code>body</code>:</p>
    <pre>
      &lt;script type="text/x-smcat"> on [color="darkgreen" active], off
      [color="maroon"]; on => off [color="red"]: flickSwitch() /
      makeNoise("off.wav"); off => on [color="#009900"]: flickSwitch() /
      makeNoise("on.wav"); &lt;/script></pre>
    <p>result:</p>
    <center>
      <script type="text/x-smcat">
        on [color="darkgreen" active], off [color="maroon"]; on => off
        [color="red"]: flickSwitch() / makeNoise("off.wav"); off => on
        [color="#009900"]: flickSwitch() / makeNoise("on.wav");
      </script>
    </center>

    <h2>Introduction</h2>
    <p>
      When you include the state-machine-cat 'inpage' script in the head of your
      page like so ...
    </p>
    <pre>&lt;script
      src="https://state-machine-cat.js.org/state-machine-cat-inpage.min.js"
      type="module" defer> &lt;/script></pre>
    <p>
      ... it will extend html with three script types, which will render into
      state machine diagrams:
      <table>
        <thead><tr><th>type</th><th>what's it do?</th></tr></thead>
        <tbody>
          <tr>
            <td>
              <code>text/x-smcat</code>
            </td>
            <td>accepts <code>smcat</code></td>
          </tr>
          <tr>
            <td>
              <code>text/x-scxml</code>
            </td>
            <td>accepts <code>SCXML</code></td>
          </tr>
          <tr>
            <td>
              <code>text/x-smcat-json</code>
            </td>
            <td>accepts smcat's abstract syntax tree format</td>
          </tr>
        </tbody>
      </table>
    </p>

    <p>
      When that is done, you can use
      <code>script</code>s with one of the types above in the body of your page
      (e.g.
      <code>&lt;script type="text/x-smcat">a=>b;&lt;/script></code>).
    </p>
    <p>
      These scripts take optional
      <code>data</code>
      attributes you can use to influence how things get rendered:
      <table>
        <thead>
          <tr>
            <th>attribute</th>
            <th>description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <code>data-direction</code>
            </td>
            <td>
              Direction the graph should be rendered in. Possible values:
              <code>top-down</code>
              (default),
              <code>left-right</code>,
              <code>bottom-top</code>,
              <code>right-left</code>.
            </td>
          </tr>
          <tr>
            <td>
              <code>data-output-type</code>
            </td>
            <td>
              What you want to have rendered. Defaults to
              <code>svg</code>
              (for diagrams), but it's also possible to re-render the state
              machine in one of the avaible description languages:
              <code>smcat</code>,
              <code>scxml</code>
              and
              <code>json</code>.
            </td>
          </tr>
          <tr>
            <td>
              <code>data-engine</code>
            </td>
            <td>
              state-machine-cat currently uses
              <a href="https://graphviz.org">GraphViz</a>
              as a render engine. With the `data-engine` attribute it's possible
              to influence which layout algorithm GraphViz uses. By default it's
              <code>dot</code>, but it's also possible to specify other values
              are e.g.
              <code>fdp</code>
              or
              <code>osage</code>.
            </td>
          </tr>
          <tr>
            <td>data-desugar</td>
            <td>Boolean attribute that, when included, will make the render
              engine
              <a
                href="https://github.com/sverweij/state-machine-cat/blob/main/docs/desugar.md"
              >desugar</a>
              the diagram.
            </td>
          </tr>
        </tbody>
      </table>
    </p>

    <h2>Examples</h2>

    <h3>Read from an url</h3>
    <p>Pass the url in the <code>src</code> attribute of the script tag:</p>
    <pre>&lt;script type="text/x-smcat"
      <mark>src="samples/cat.smcat"</mark>>&lt;/script></pre>
    <center>
      <script type="text/x-smcat" src="samples/cat.smcat"></script>
    </center>

    <h2>Orientation with <code>data-direction</code></h2>
    <p>
      In this example the states get layed out from left to right instead of top
      down because the script includes the
      <code>data-direction</code>
      attribute:
    </p>
    <pre>
      &lt;script type="text/x-smcat" src="samples/cassetteplayer.smcat"
      <mark>data-direction="left-right"</mark>> &lt;/script></pre>
    <center>
      <script
        type="text/x-smcat"
        src="samples/cassetteplayer.smcat"
        data-direction="left-right"
      ></script>
    </center>

    <h2>De-sugaring a state machine</h2>
    <p>
      If you want to render a state machine without any pseudo states that only
      exist for 'syntactic sugar', you can do this with the `data-desugar`
      attribute.
    </p>
    <h3>as is</h3>
    <pre>
      &ltscript src="samples/desugarable.smcat" type="text/x-smcat"
      data-direction="left-right" &lt/script></pre>

    <script
      src="samples/desugarable.smcat"
      type="text/x-smcat"
      data-direction="left-right"
    ></script>

    <h3>de-sugared</h3>
    <pre>
      &ltscript src="samples/desugarable.smcat" type="text/x-smcat"
      data-direction="left-right"
      <mark>data-desugar=true</mark>> &lt/script></pre>
    <p>
      You'll notice the
      <em>choice</em>
      is replaced by two regular transitions and the
      <em>junction</em>
      on the right with all permutations of transitions it describes:
    </p>
    <script
      src="samples/desugarable.smcat"
      type="text/x-smcat"
      data-desugar="true"
      data-direction="left-right"
    ></script>

    <h2>Using SCXML</h2>
    <p>
      It's possible to embed SCXML:
    </p>
    <pre>
      &lt;script
      <mark>type="text/x-scxml"</mark>> &lt;scxml
      xmlns="http://www.w3.org/2005/07/scxml" version="1.0"> &lt;state id="off">
      &lt;onentry>&lt;log expr="winston.log('switched lamp on')"/>&lt;/onentry>
      &lt;transition event="switch_flipped" target="on"/> &lt;/state> &lt;state
      id="on"> &lt;transition event="switch_flipped" target="off"/> &lt;/state>
      &lt;/scxml> &lt;/script></pre>
    <center>
      <script type="text/x-scxml">
        <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"> <state
        id="off"> <onentry><log expr="winston.log('switched lamp
        on')"/></onentry> <transition event="switch_flipped" target="on"/>
        </state> <state id="on"> <transition event="switch_flipped"
        target="off"/> </state> </scxml>
      </script>
    </center>

    <p>
      or likewise, using a
      <code>src</code>
      attribute to load SCXML from somewhere else:
    </p>
    <pre>&ltscript
      <mark>type="text/x-scxml" src="samples/sprint-states.scxml"</mark>>&lt/script></pre>
    <center>
      <script
        type="text/x-scxml"
        src="samples/sprint-states.scxml"
      ></script>
    </center>

    <h2>Output formats other than <code>svg</code></h2>
    <p>
      If you, for some reason don't want to render an svg, but one of the
      textual formats, you can specify an output type. This example specifies
      <code>json</code>
      to show the abstract syntax tree (AST):
    </p>
    <pre>&lt;script type="text/x-smcat" data-output-type="json"> off: entry/
      &lt;log expr="winston.log('switched lamp on')"/>, on; off => on:
      switch_flipped; on => off: switch_flipped; &lt;/script></pre>

    <p>which will render this AST:</p>
    <script type="text/x-smcat" data-output-type="json">
      off: entry/ <log expr="winston.log('switched lamp on')"/>, on; off => on:
      switch_flipped; on => off: switch_flipped;</script>

    <h2>Error handling</h2>
    <p>
      When the render engine detects an error it will show the error. E.g.
      trying to render an invalid script, like so...
    </p>
    <pre>&lt;script type="text/x-smcat">a => nosemicolon&lt;/script></pre>

    <p>
      ... will yield this:
    </p>

    <script type="text/x-smcat">a => nosemicolon</script>

    <p>
      ... or when it couldn't find the script at the other end of the URL ...
    </p>

    <pre>&lt;script src="this_thing_doesnot_exist" type="text/x-smcat"/></pre>

    <script src="this_thing_doesnot_exist" type="text/x-smcat"></script>
  </body>
</html>